"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Postgresql = exports.pgp = void 0;
const dbClient_1 = require("./dbClient");
const common_1 = require("../common");
const pgPromise = require("pg-promise");
exports.pgp = pgPromise({
    capSQL: true,
    error(error, e) {
        if (e.cn) {
            console.error('Connection error:', error.message || error);
        }
        if (e.query) {
            console.error('Query error:', error.message || error);
            console.error('Query:', e.query);
        }
    }
});
// BIGINT | BIGSERIAL 转化
exports.pgp.pg.types.setTypeParser(20, parseInt);
// decimal 转化
exports.pgp.pg.types.setTypeParser(1700, parseFloat);
class PostgresqlTransaction extends dbClient_1.Transaction {
    constructor(t) {
        super();
        this.t = t;
    }
    async oneOrNone(sql) {
        return this.t.oneOrNone(sql);
    }
    async one(sql) {
        return this.t.one(sql);
    }
    async query(sql) {
        return this.t.query(sql);
    }
    async none(sql) {
        await this.t.none(sql);
    }
}
class Postgresql extends dbClient_1.DbClient {
    constructor({ host, port, database, user, password }) {
        const config = { host, port, database, user, password };
        super(config);
        this.client = (0, exports.pgp)({});
        if (Object.values(config).filter(Boolean).length > 0) {
            this.client = (0, exports.pgp)({
                host: this.host,
                port: this.port,
                database: this.database,
                user: this.user,
                password: this.password,
                max: 20,
                idleTimeoutMillis: 30000,
                connectionTimeoutMillis: 2000,
            });
        }
    }
    setConnection(connection) {
        this.client = connection;
    }
    async connect() {
        try {
            await this.client.connect();
            console.info(`Connected to postgres: ${this.host}`);
        }
        catch (e) {
            console.error('PostgreSQL connection error:', e);
            throw new Error(`Failed to connect to PostgreSQL: ${e.message}`);
        }
    }
    getExecutor(transaction) {
        return transaction ? transaction : this.client;
    }
    async oneOrNone(sql, transaction) {
        return this.getExecutor(transaction).oneOrNone(sql);
    }
    async one(sql, transaction) {
        return this.getExecutor(transaction).one(sql);
    }
    async query(sql, transaction) {
        return this.getExecutor(transaction).query(sql);
    }
    async none(sql, transaction) {
        await this.getExecutor(transaction).none(sql);
    }
    async tx(func) {
        return this.client.tx(async (t) => {
            const transaction = new PostgresqlTransaction(t);
            return await func(transaction);
        });
    }
    insertSql(data, cs, tableConfig) {
        const returnIdSql = tableConfig.createReturn ? ` RETURNING ${tableConfig.idName}` : '';
        return exports.pgp.helpers.insert(data, cs) + returnIdSql;
    }
    updateSql(data, cs, tableConfig) {
        return exports.pgp.helpers.update(data, cs);
    }
    static geomProcess(content = [], geomPropertyName = 'geom') {
        content.forEach((value) => {
            const geom = value[geomPropertyName];
            if (geom) {
                const geomStr = geom.replace("POINT(", "").replace(")", "");
                const [lng, lat] = geomStr.split(' ').map(Number);
                value[geomPropertyName] = { lng, lat };
            }
        });
    }
    static geomSaveProcess(entity, geomPropertyName = 'geom', srid = `4326`) {
        let lng, lat;
        const geom = entity[geomPropertyName];
        if (geom == null) {
            return;
        }
        try {
            ({ lng, lat } = geom);
        }
        catch (e) {
            throw new common_1.ValidationError('geom 属性格式错误');
        }
        entity[geomPropertyName] = `SRID=${srid};POINT(${lng} ${lat})`;
    }
    columnProcess(s) {
        return `"${s}"`;
    }
}
exports.Postgresql = Postgresql;
